package com.lhd.service.ws;

import com.alibaba.excel.util.StringUtils;
import com.lhd.entity.dto.PostActivityDto;
import com.lhd.entity.enums.RoleEnum;
import com.lhd.entity.po.Course;
import com.lhd.entity.po.UserSysClass;
import com.lhd.entity.query.CourseQuery;
import com.lhd.entity.query.RecordQuery;
import com.lhd.entity.query.UserSysClassQuery;
import com.lhd.entity.vo.InformVO;
import com.lhd.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;


/**
 * @Author: liuhd
 * @Date: 2025/4/12 17:42
 * @Description: WebSocket服务端
 */

@Component
@Slf4j
@ServerEndpoint("/pushMessage/{userId}")
public class InformServer {
    // 关键点：必须使用静态变量持有 Service
    private static CourseService courseService;
    private static UserSysClassService userSysClassService;
    private static RecordService recordService;

    // Spring Boot 专用注入方式：通过 Setter 初始化静态变量
    @Autowired
    public void setStaticServices(
            CourseService courseService,
            UserSysClassService userSysClassService,
            RecordService recordService
    ) {
        InformServer.courseService = courseService;
        InformServer.userSysClassService = userSysClassService;
        InformServer.recordService = recordService;
    }

    private static final ConcurrentHashMap<String, InformServer> webSocketMap = new ConcurrentHashMap<>();
    /**与某个客户端的连接会话，需要通过它来给客户端发送数据*/
    private Session session;
    /**接收userId*/
    private String userId;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        this.userId = userId;
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            // 加入map中
            webSocketMap.put(userId, this);
        } else {
            // 加入map中
            webSocketMap.put(userId, this);
        }
        log.info("用户连接:" + userId);
        sendMessage("连接成功");
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            log.info("用户断开连接:" + userId);
        }
    }

    /**
     * 收到客户端消息后调用的方法,通知所有学生
     **/
    @OnMessage
    public void onMessage(String message) {
        log.info("Service 依赖检查: courseService={}", courseService);
        log.info("用户消息:" + userId + ",报文:" + message);
        // 解析成对象
        PostActivityDto postActivityDto = JSON.parseObject(message, PostActivityDto.class);

        // 查出各班级所有的学生
        UserSysClassQuery userSysClassQuery = new UserSysClassQuery();
        userSysClassQuery.setSidList(postActivityDto.getSidList());
        userSysClassQuery.setRole(RoleEnum.STUDENT.getCode());
         // 联表查询
        List<UserSysClass> studentList = userSysClassService.findStudentList(userSysClassQuery);
        List<Integer> studentIdList = new ArrayList<>();
        for (UserSysClass userSysClass : studentList) {
            studentIdList.add(userSysClass.getUid());
        }

        // 构建消息
        InformVO informVO = new InformVO();

        // 学生收到的课程/标题信息
         // 课程信息
        CourseQuery courseQuery = new CourseQuery();
        courseQuery.setId(postActivityDto.getCid());
        List<Course> courseList = courseService.findListByQuery(courseQuery);
        Course course = courseList.get(0);
        String courseName = course.getName();
         // 标题信息
        String title = postActivityDto.getTitle();
        // 是否需要验证码
        Integer isVerify = postActivityDto.getIsVerify();
        // 剩余时间（活动时间 + 迟到时间）
        Integer lastTime = postActivityDto.getLastTime();
        Integer lateTime = postActivityDto.getLateTime();
        // 查询学生对应的活动id，同时构建通知信息
        for (Integer stuId : studentIdList) {
            informVO.setStuId(stuId);
            informVO.setCourseName(courseName);
            informVO.setIsVerify(isVerify);
            informVO.setTitle(title);
            informVO.setLastTime(lastTime);
            informVO.setLateTime(lateTime);
            RecordQuery recordQuery = new RecordQuery();
            recordQuery.setStuId(stuId);
            Integer aid = recordService.findListByQuery(recordQuery).get(0).getAid();
            informVO.setAid(aid);

            // 将 InformVO 转换为 JSON 字符串并发送
            String jsonMessage = JSON.toJSONString(informVO);
            sendInfo(jsonMessage, String.valueOf(stuId));
        }
    }


    /**
     * 发生异常调用方法
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) {
        this.session.getAsyncRemote().sendText(message);
    }

    /**
     *发送自定义消息
     **/
    public static void sendInfo(String message, String userId) {
        log.info("发送消息到:" + userId + "，报文:" + message);
        if (StringUtils.isNotBlank(userId) && webSocketMap.containsKey(userId)) {
            webSocketMap.get(userId).sendMessage(message);
        } else {
            log.error("用户" + userId + ",不在线！");
        }
    }
}